import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 
 */

/**
 * @author zero
 * 
 */
public class Shape
{
    private int                       x;
    private int                       y;
    private int                       width;
    private int                       height;
    private int                       bottom;
    private int                       top;
    private int                       left;
    private int                       right;

    private List<Block>               blockList       = new ArrayList<Block>();

    private Map<Integer, List<Block>> blockPostionMap = new HashMap<Integer, List<Block>>();

    private int                       bottomY;

    public int getLeftestBlockX()
    {

        List<Block> blockList = blockPostionMap.get(x);
        return blockList.get(0).x;
    }

    public int getRightestBlockX()
    {

        List<Block> blockList = blockPostionMap.get(x + width);
        return blockList.get(0).x;
    }

    public int getLowestBlockYByX(int x)
    {
        List<Block> blockList = blockPostionMap.get(x);

        return blockList.get(0).y;
    }

    protected int getLowestBlockY()
    {
        int lowestY = Integer.MAX_VALUE;
        for (List<Block> blockList : blockPostionMap.values())
        {
            if (blockList.get(0).y < lowestY)
            {
                lowestY = blockList.get(0).y;
            }
        }
        return lowestY;
    }

    private void addBlockToPostion(Block block)
    {
        List<Block> blockList = blockPostionMap.get(block.x);
        if (null == blockList)
        {
            blockList = new ArrayList<Block>();
            blockPostionMap.put(block.x, blockList);
        }

        blockList.add(block);
    }

    private void addBlockListByPostion(Integer pos, List<Block> blockList)
    {
        blockPostionMap.put(pos, blockList);
    }

    private void delBlockListByPostion(Integer pos)
    {
        blockPostionMap.remove(pos);
    }

    public Shape[] devideIntoShapes(int devideX)
    {
        // left, middle and right
        Shape[] shapes = new Shape[3];

        int leftX = x;
        int widthLeft = devideX - x;
        int rightX = devideX + 1;
        int widthRight = x + width - (devideX + 1);

        if (widthLeft > 0)
        {

            Shape shapeLeft = new Shape();
            List<Block> leftBlocks = null;

            boolean hasBlock = false;
            for (int i = leftX; i < leftX + widthRight; ++i)
            {
                leftBlocks = blockPostionMap.get(i);
                if (leftBlocks.size() > 0)
                {
                    hasBlock = true;
                    shapeLeft.addBlockListByPostion(i, leftBlocks);
                    this.delBlockListByPostion(i);
                }
            }

            if (hasBlock)
            {
                shapes[0] = shapeLeft;
            }
        }

        if (widthRight > 0)
        {

            Shape shapeLeft = new Shape();
            List<Block> rightBlocks = null;
            boolean hasBlock = false;
            for (int i = rightX; i < rightX + widthRight; ++i)
            {
                rightBlocks = blockPostionMap.get(i);
                if (rightBlocks.size() > 0)
                {
                    shapeLeft.addBlockListByPostion(i, rightBlocks);
                    this.delBlockListByPostion(i);
                }
            }

            if(hasBlock)
            {
                shapes[2] = shapeLeft;
            }
        }

        Shape shapeMiddle = this;
        List<Block> midBlocks = blockPostionMap.get(devideX);
        shapeMiddle.addBlockListByPostion(devideX, midBlocks);

        shapes[1] = shapeMiddle;

        return shapes;
    }

    public void moveDown()
    {
        for (Block block : blockList)
        {
            block.moveDown();
        }
    }

    /**
     * @return the x
     */
    public int getX()
    {
        return this.x;
    }

    /**
     * @param x
     *            the x to set
     */
    public void setX(int x)
    {
        this.x = x;
    }

    /**
     * @return the y
     */
    public int getY()
    {
        return this.y;
    }

    /**
     * @param y
     *            the y to set
     */
    public void setY(int y)
    {
        this.y = y;
    }

    /**
     * @return the width
     */
    public int getWidth()
    {
        return this.width;
    }

    /**
     * @param width
     *            the width to set
     */
    public void setWidth(int width)
    {
        this.width = width;
    }

    /**
     * @return the height
     */
    public int getHeight()
    {
        return this.height;
    }

    /**
     * @param height
     *            the height to set
     */
    public void setHeight(int height)
    {
        this.height = height;
    }

    /**
     * @return the bottom
     */
    public int getBottom()
    {
        return this.bottom;
    }

    /**
     * @param bottom
     *            the bottom to set
     */
    public void setBottom(int bottom)
    {
        this.bottom = bottom;
    }

    /**
     * @return the bottomY
     */
    public int getBottomY()
    {
        return this.bottomY;
    }

    /**
     * @param bottomY
     *            the bottomY to set
     */
    public void setBottomY(int bottomY)
    {
        this.bottomY = bottomY;
    }

}
